// --------------------------------------------------------------------------------------------------------------------
// <copyright file="HalfSpaceRegion.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Microsoft.Robotics.Numerics
{
    using System.Runtime.Serialization;

    /// <summary>
    /// represent a half space region
    /// </summary>
    [DataContract]
    public class HalfSpaceRegion
    {
        /// <summary>
        /// the normal of the plane, which defines the positive side of the space
        /// the half space the normal is pointing to is positive
        /// </summary>
        [DataMember]
        private readonly Vector3 normal;

        /// <summary>
        /// The signed distance from the plane to the origin of the space.
        /// If the origin is on the positive side of the plane, the distance is positive;
        /// otherwise, the distance is negative.
        /// This is a part of the Hessian normal form (see the link below), which is used
        /// here for the ease of computation.
        /// </summary>
        [DataMember]
        private readonly double signedDistanceToOrigin;

        /// <summary>
        /// Initializes a new instance of the <see cref="HalfSpaceRegion" /> class.
        /// Given the normal of the plane and a point that is on the plane, this constructor
        /// generates a plane in the form of n * (x - x0) = 0, which divides the space into
        /// two half spaces.
        /// The half space the normal n points to is the positive half space.
        /// Assumption made here is that the positive half space is accessible(safe)
        /// and the negative half space is inaccessible.
        /// </summary>
        /// <param name="n">The normal of the plane.  This defines the positive and negative
        /// half spaces: the positive half space is the one the normal points to.
        /// This vector should be a unit vector, but it will be always normalized.</param>
        /// <param name="x0">a point that is on the plane</param>
        //// a link to the plane representation http://mathworld.wolfram.com/Plane.html
        public HalfSpaceRegion(Vector3 n, Vector3 x0)
        {
            this.normal = Vector3.Normalize(n);
            this.signedDistanceToOrigin = -Vector3.Dot(this.normal, x0);
        }

        /// <summary>
        /// Given a point in space, returns a boolean indicating whether this point
        /// is on the negative side of the half space
        /// </summary>
        /// <param name="point">a point in space</param>
        /// <returns>whether the point is on the negative side</returns>
        public bool IsOnTheNegativeSide(Vector3 point)
        {
            return Vector3.Dot(this.normal, point) + this.signedDistanceToOrigin <= 0;
        }
    }
}
